iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
Modern Web

現在就學Node.js系列 第 6

Path 模組 — 檔案路徑處理全攻略 - Day6

  • 分享至 

  • xImage
  •  

昨天學習 Node.js 的模組系統,今天要進入另一個開發中常使用的好朋友:Path 模組

它的角色就像「地圖專家」,幫我們正確處理檔案路徑,

無論你在 Windows、macOS、Linux,寫出來的程式都能順利運作。


為什麼要用 path

如果直接用字串拼路徑,常常會踩坑:

  • 跨平台問題:Windows 用 \,Linux/Mac 用 /
  • 相對路徑容易迷路./../ 稍不注意就會找錯地方。
  • 取檔名或副檔名麻煩:用字串切割超難維護。

👉 這些問題交給 path,都能輕鬆解決。

範例專案結構

project/
  ├── index.js
  ├── notes.txt
  ├── images/
  │     └── logo.png
  └── data/
        └── users.json

常用方法

以下範例假設在 project/index.js 執行:

import path from "node:path";

const filePath = path.join("project", "data", "users.json");

console.log("完整路徑:", filePath);
console.log("檔名:", path.basename(filePath));
console.log("副檔名:", path.extname(filePath));
console.log("所在目錄:", path.dirname(filePath));

輸出:

完整路徑: project/data/users.json
檔名: users.json
副檔名: .json
所在目錄: project/data

常見 API

  1. path.join(...segments) → 安全拼接路徑(會自動處理 /\)。
  2. path.resolve(...segments) → 一定會回傳絕對路徑。
  3. path.basename(p) → 取檔名(含副檔名)。
  4. path.extname(p) → 取副檔名。
  5. path.dirname(p) → 取目錄名稱。
  6. path.parse(p) → 把路徑拆成物件(root、dir、name、ext…)。
  7. path.format(obj) → 把物件重新組合成路徑。

path.join()path.**resolve**()的差異

path.join()

  • 單純拼接段落,再標準化(處理 ...)。
  • 不一定會變成絕對路徑。
  • 遇到絕對路徑片段,會以該片段為起點
path.join('project', 'data', 'users.json');
// → 'project/data/users.json'

path.join('/foo', '/bar', 'baz');
// → '/bar/baz'

path.resolve()

  • 從右到左拼接,遇到第一個絕對路徑就當成根。
  • 一定會輸出絕對路徑
  • 沒有絕對片段時,會以當前工作目錄 (CWD) 為基準。
path.resolve('project', 'data', 'users.json');
// → /Users/you/current-dir/project/data/users.json

path.resolve('/foo', 'bar', 'baz');
// → /foo/bar/baz

  • join = 組字串。
  • resolve = 求絕對路徑。

path.parse()path.format()

path.parse(p)

把路徑拆解成物件:

const info = path.parse('/Users/you/project/data/users.json');
console.log(info);

結果:

{
  "root": "/",
  "dir": "/Users/you/project/data",
  "base": "users.json",
  "ext": ".json",
  "name": "users"
}

path.format(obj)

把物件組回路徑:

const newPath = path.format({
  dir: '/Users/you/project/data',
  name: 'users.v2',
  ext: '.json'
});

console.log(newPath);
// → /Users/you/project/data/users.v2.json

絕對路徑 vs 相對路徑

  • 絕對路徑:從磁碟根開始,例如:
    • Windows → C:\Users\you\project\data\users.json
    • macOS/Linux → /Users/you/project/data/users.json
  • 相對路徑:依賴「程式執行位置」計算,例如:
    • ./data/users.json
    • ../images/logo.png

⚠️ 常見錯誤:相對路徑不是檔案所在目錄

很多人會這樣寫:

import fs from "node:fs";

fs.readFile("./data/file.txt", "utf-8", (err, data) => {
  if (err) throw err;
  console.log(data);
});

這裡的 ./data/file.txt 不是程式檔案所在的資料夾,而是「程式執行時的工作目錄 (process.cwd())」。


./ vs __dirname vs process.cwd() 比較表

名稱 代表什麼? 特點 什麼時候用?
./ 執行時的相對路徑 相對於「在哪個資料夾執行 node 指令」 不穩定,容易出錯
__dirname 程式檔案所在的資料夾 與程式碼位置綁定,不受執行位置影響 ✅ 推薦用於讀寫檔案
process.cwd() 程式執行時的工作目錄 ./ 等價,可用來檢查當前目錄 CLI 工具、專案根目錄

舉例

專案結構:

project/
  ├── index.js
  └── data/
       └── file.txt

情境一(在 project/ 內執行):

cd project
node index.js   # ✅ 可以找到 data/file.txt

情境二(在上一層執行):

cd ..
node project/index.js   # ❌ 找不到 data/file.txt

因為此時 ./ 指的是「上一層資料夾」,不是 project


解法:搭配 __dirname

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const filePath = path.resolve(__dirname, "data", "file.txt");

fs.readFile(filePath, "utf-8", (err, data) => {
  if (err) throw err;
  console.log(data);
});

這樣不管你在哪個資料夾執行,都能正確找到 data/file.txt

小結

今天我們學到:

  1. join vs resolve → 前者拼接路徑,後者算絕對路徑。

  2. basenameextnamedirname → 快速取檔名、附檔名與目錄。

  3. parseformat → 路徑物件與字串互轉。

  4. ⚠️ 陷阱:相對路徑依賴「執行位置」,不是檔案位置。

    → 解法:搭配 __dirname + path.resolve()


上一篇
CommonJS (CJS) vs ES Modules (ESM) — Node.js 模組系統 - Day5
下一篇
Node.js 之 fs 檔案系統 - Day7
系列文
現在就學Node.js7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言